graphql-upload with cloudinary
Hi. I am using apollo-upload-client and graphql-upload to upload an image to our node js server
i am able to successfully upload the image onto my node server with the following data
{ filename: 'IMG_20181113_152536.jpg',
mimetype: 'image/jpeg',
encoding: '7bit',
createReadStream: [Function: createReadStream] }
from reading your documentation, i believe i need to use the cloudinary stream to upload the image to the cloudinary to host it.
var fs = require('fs'); var stream = cloudinary.v2.uploader.upload_stream(function(error, result){console.log(result, error)}); var file_reader = fs.createReadStream('my_picture.jpg').pipe(stream)
However, i am unable to get the stream to work. Any working example I can refer? or what do I need to do to make it work? Also, once, the image has been successfully streamed to cloudinary for hosting, it will return me a link (cloudinary url) right? cause i need that to insert into our database]
Thanks in advance. Hendry
-
Hi Hendry,
Please take a look at the upload stream examples on our repo-https://github.com/cloudinary/cloudinary_npm/blob/bf7103aac2714002305566d05a53ded4cdcafbca/samples/basic/basic.js#L32
var upload_stream= cloudinary.v2.uploader.upload_stream({tags: 'basic_sample'},function(err,image) {
console.log('here');
console.log("** Stream Upload");
//if (err){ console.warn(err);}
console.log("* Same image, uploaded via stream");
console.log("* "+image.public_id);
console.log("* "+image.url);
});
var file_reader = fs.createReadStream('<local_file_name>').pipe(upload_stream);You'll then get the URL in the resonse as seen above
0 -
Hi Raya,
thanks for your pointers. I am still unable to get it to work. I am not very familiar with how stream works. I plugged in my stream object at fs.createReadStream. is that correct? or should I insert my stream in another portion of the code? Tq
Below is my mutation codes
import * as fs from "fs";import cloudinary from "cloudinary";Mutation: {uploadPicture:async (_, { file }) => {const { stream } =await file;console.log("stream ", stream);
try {//TODO upload to cloudinaryconst upload_stream=cloudinary.uploader.upload_stream({ tags: "sample" },function(err:any, image:any) {console.log();console.log("** Stream Upload");if (err) {console.warn(err);}console.log("* Same image, uploaded via stream");console.log("* "+image.public_id);console.log("* "+image.url);});const file_reader=fs.createReadStream(stream).pipe(upload_stream);console.log(file_reader);} catch (error) {throwerror;}returntrue;},0 -
Are you seeing any errors? Also, it looks like you're missing the v2 from your request. Can you please try adding it? cloudinary.v2.uploader.upload_stream...
0 -
I tried adding v2 but still can't work. I don't see any error messages on console. I m not familiar with working with streams. Is it correct that I pass the stream object which I get from graphql-upload directly to the createReadStream and that is supposed to work?
const file_reader=fs.createReadStream(stream).pipe(upload_stream);
0 -
Hendry, you dont need the createReadStream() call because the stream that is sent from the apollo client is already a readable stream, you should be able to call stream.pipe(upload_stream) and have it work
1 -
Thanks Matthew! It worked. Below are my codes for those who are using graphql-upload with cloudinary
const cloudinaryUpload = async ({ stream }: any): Promise<any> => {const streamLoad = cloudinary.v2.uploader.upload_stream(function(error:any,result:any) {if (result) {console.log("result ", result);} else {console.log("error ", error);}});
stream.pipe(streamLoad);
return`Test`;};
export const processCloudinaryUpload = async (upload: any) => {const { stream } =await upload;
await cloudinaryUpload({ stream });
};0 -
Thank you for pointing out Matthew and Hendry for your update!
0 -
Thank you for the code ! It has been very useful for me. This is the one I did (it might have some mistakes, as I am a newbie but is working), inspired from Hendry and Jayden Seric :
with authentication, for single and multiple uploads, requires npm package promises-all :
import promisesAll from 'promises-all';
const processUpload= async upload => {
const {stream }= await upload;
const cloudinary = require('cloudinary');
cloudinary.config(
{
cloud_name: 'your-cloud-name',
api_key: 'your-api-key',
api_secret: 'your-api-secret'
}
);
let resultUrl = '', resultSecureUrl = '';
const cloudinaryUpload = async ({stream}) => {
try {
await new Promise((resolve, reject) => {
const streamLoad = cloudinary.v2.uploader.upload_stream(function (error, result) {
if (result) {
resultUrl = result.secure_url;
resultSecureUrl = result.secure_url;
resolve(resultUrl)
} else {
reject(error);
}
});
stream.pipe(streamLoad);
});
}
catch (err) {
throw new Error(`Failed to upload profile picture ! Err:${err.message}`);
}
};
await cloudinaryUpload({stream});
return(resultUrl)
};
Mutation : {
async singleFileUpload(parent, {file}) {
return(processUpload(file))
},
async multipleFileUpload(parent, {files}) {
const {resolve, reject} = await promisesAll.all(
files.map(processUpload)
);
if (reject.length) {
reject.forEach(
({name, message}) => {
console.error(`${name}:${message}`)
}
)
}
return resolve;
},
}1 -
Thanks Guillaume! your codes help in getting a url response from the server. tq :)
0 -
const cloudinary = require("cloudinary").v2;
Hello, am having similar issue, i tried to follow the example above but is still not work.
Am using apollo graphql to pass body of post and file upload, at the backend i console.log(file) and it shows the result below but i console.log(stream) it gives undefile . am trying to store it cloudinary before storing the link at MongoDb, but is the storing of the file at cloudinary working.
Am having this error "
- TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be one of type string, Buffer, or URL. Received type undefined"
The is the mutation
mutation ($body: String!, $file : Upload){createPost(body: $body, file: $file){id body createdAt username
likes{id createdAt username}likeCountcomments{id body createdAt username
}commentCount}}`;Thanks for your help0 -
Hi Duke,
As Matthew said you don't need the createReadStream()
Can you try again with the previous sample code:
```
try {
await new Promise((resolve, reject) => {
const streamLoad = cloudinary.v2.uploader.upload_stream(function (error, result) {
if (result) {
resultUrl = result.secure_url;
resultSecureUrl = result.secure_url;
resolve(resultUrl)
} else {
reject(error);
}
});
stream.pipe(streamLoad);
});
}Thanks,
0 -
Thanks Shirly Manor for your reply
I have tried it but it gives an error " ReferenceError: stream is not defined "
I also console.log(stream) but it gives undefined , is stream supposed to be undefined ?.
but if console.log(file) it give the result as shown
Server running at http://localhost:5000/
Promise {
{ filename: 'Screenshot 2019-07-29 at 12.59.53.png',
mimetype: 'image/png',
encoding: '7bit',
createReadStream: [Function: createReadStream] } }0 -
Hi Duke,
Did you initiate the stream?
e.g.:
```
const { stream } =await upload;
```
0 -
Thanks
It works now but i am having this message about depreciation
" (node:3979) DeprecationWarning: File upload property ‘stream’ is deprecated. Use ‘createReadStream()’ instead "
since is depreciated will stop working ?
if i want to use this then var file_reader = fs.createReadStream('<local_file_name>').pipe(upload_stream);,
what is the '<local_file_name>' , i tried to use the finename but is not working
0 -
Hi Duke,
When I google it, I found that the filename is the local directory and the file name. e.g, `dev/test.txt`.
You can read about it here:
https://nodejs.org/en/knowledge/advanced/streams/how-to-use-fs-create-read-stream/
Thanks,
0 -
Thanks to everyone on this thread. Also noting that this only works with images by default, if you try to upload a video, it will give you the error: 'Invalid image file'.
To upload videos, add { resource_type: 'video' } as the first argument of your uploader.upload_stream() method.0 -
Hi Carolina,
Yes, the default value for uploading for the
resource_type parameter
isimage
, so you must set theresource_type
parameter and set it to "video" when uploading videos.You can read more about that here:
https://cloudinary.com/documentation/upload_images#uploading_videos
0 -
Hi there, i have same issues i cant figure it out so this is my mutation =======>
------ MUTATION -------
```
t.field('uploadSupportAttachment', {type: 'FileUpload',args: {file: arg({ type:'Upload' }),},resolve: async (_, { file }, ctx) => {const result = await uploadFile(file)return file},})```this is my utils ======>
----- UTILS -----
```export const uploadFile = async (file: any) => {cloudinary.v2.config({cloud_name: '////',api_key: '////',api_secret: '////',})const { createReadStream, filename } = await fileconst fileStream = createReadStream()
const streamLoad = cloudinary.v2.uploader.upload_stream({ timeout: 120000 },error: any,result: any) {if (result) {console.log('result ', result)} else {console.log('error ', error)}})fileStream.pipe(streamLoad)return''}```what i receive from front is ====>Promise {
{
filename: 'drilldown.png',
mimetype: 'image/png',
encoding: '7bit',
createReadStream: [Function: createReadStream]
}
}i cant stop to have this ====> error {
message: 'Server returned unexpected status code - 504',
http_code: 504,
name: 'UnexpectedResponse'
}someone can help ??? thanks in advance0 -
Hi Lucas,
You can read more on how to use the upload_stream here:
0 -
If you're using apollo-upload-client on the client-side, the easiest way is to use the createReadStream function that the uploaded image resolves to, and pipe that stream directly to Cloudinary.
const { createReadStream, filename, mimetype, encoding } = await image;try {result = awaitnewPromise((resolve, reject) => {createReadStream().pipe(cloudinary.uploader.upload_stream((error, result) => {if (error) {console.log(error);}
console.log('image uploaded');}));});} catch (error) {console.log(error);}0
Post is closed for comments.
Comments
20 comments