node-formidable / formidable

The most used, flexible, fast and streaming parser for multipart form data. Supports uploading to serverless environments, AWS S3, Azure, GCP or the filesystem. Used in production.
MIT License
7.06k stars 682 forks source link

Same file upload will upload again with a different name, instead of beeing cache like where only the name is returned #648

Closed banli17 closed 3 years ago

banli17 commented 4 years ago

hi, i found same file upload will return different name,and this will create many files, i want upload same file. return the same file,please help me, i found this code

IncomingForm.prototype._uploadPath = function(filename) {
  var buf = crypto.randomBytes(16);
  var name = 'upload_' + buf.toString('hex');

  if (this.keepExtensions) {
    var ext = path.extname(filename);
    ext     = ext.replace(/(\.[a-z0-9]+).*/i, '$1');

    name += ext;
  }

  return path.join(this.uploadDir, name);
};
auto-comment[bot] commented 4 years ago

Thank you for raising this issue! We will try and get back to you as soon as possible. Please make sure you format it properly, followed our code of conduct and have given us as much context as possible. /cc @tunnckoCore @GrosSacASac

banli17 commented 4 years ago

but if i upload same file , it will recreate a new file with the same name。how can i avoid it。

i want to if the file is exist,not create

tunnckoCore commented 4 years ago

You don't need to override internal functions, there's not documented options.filename in the v2 (canary).

https://github.com/node-formidable/formidable/blob/5110ef8ddb78501dcedbdcb7e2754d94abe06bc5/src/Formidable.js#L60-L70

const { formidable } = require('formidable');

const form = formidable({
  keepExtensions: true, // that must be `true`
  filename: (part) => {
    // it has `part.name` and etc
    console.log(part);
  }
});

And yes, if you implement to have same name, it will probably recreate/rewrite the existing file.

One workaround could be to cache the filename in some variable outside, and check if exists (fs.existsSync()), then not call the parse (or formidable() at all) if it exists.

Sorry about that. Not possible otherwise, for the moment.

banli17 commented 4 years ago

thx @tunnckoCore

banli17 commented 4 years ago

but it sames can not rename according file's md5,part has no unique flag to rename file。

part Stream {
  _events: [Object: null prototype] {},
  _eventsCount: 0,
  _maxListeners: undefined,
  readable: true,
  headers: {
    'content-disposition': 'form-data; name="file"; filename="tpl.jpg"',
    'content-type': 'image/jpeg'
  },
  name: 'file',
  filename: 'tpl.jpg',
  mime: 'image/jpeg',
  transferEncoding: 'binary',
  transferBuffer: ''
}
const form = formidable({
            multiples: true,
            keepExtensions: true,
            uploadDir: getUploadPath('../upload_cache'),
            filename: (part) => {
                console.log(Object.keys(part))
                console.log('part', part)
            }
        });
tunnckoCore commented 4 years ago

Sorry, I can't understand your last comment. Don't feel bad to use something like Google Translate if your English isn't good! :wink: There's nothing wrong :)

After a few hours of trying how I can implement what I was thinking and proposing... I gave up, I can't come to a solution, without changes in the codebase. Even if the filename or the contents is always the same it will always overwrite its contents... I still have a feeling I can do it, but I'm not 100% sure and does not worth the time.

Fundamentals & codebase are messy, and currently we can't do some things, sorry.

banli17 commented 4 years ago

Sorry, I will use Google Translate. I want to upload the same image only once, and if it exists, it will return the name of the previously generated image (similar to cache) instead of regenerating. I'm not sure if this kind of cache is better?

tunnckoCore commented 4 years ago

Yes, I thought about that but can't think of a solution for now, sorry... :(

banli17 commented 4 years ago

thank you @tunnckoCore

GrosSacASac commented 3 years ago

https://github.com/node-formidable/formidable/pull/689 Try the branch, and use the changed filename option. Inside you can sync check existing filenames you have.

If you want to prevent duplicate file content but with different name then you have to manually compare file content after file upload and delete one.