SvelteKit 和通过 node-postgres 从 PostgreSQL 检索图像
SvelteKit and retrieving images from PostgreSQL via node-postgres
将约 100 个 JPEG(每个 24K-100K)作为 bytea 列存储在 PostgreSQL 的 table 中。
<img/>
标签 src 属性引用 SvelteKit 端点:
<img src="/api/file/18.json" alt="Person"/>
出现此错误:
Invalid response from route /api/file/76.json: Uint8Array body must be accompanied by content-type: application/octet-stream header
export async function get({ params }) {
const { id } = params
const sql = `SELECT _id, name, type, data FROM files WHERE _id = ;`
const { rows } = await db.query(sql, [id])
const file = rows[0]
return {
headers: {
'Content-disposition': `attachment; filename=${file.name}`,
'Content-type': file.type
},
body: file.data
}
}
由于 SvelteKit endpoints 不与 req/res 对象交互,因为它们只在某些平台上可用,我不能只将 bytea 值作为流写到响应对象,但是我不确定正确的方法是什么。
也试过这个SQL语句...
SELECT _id, name, type, encode(data, 'base64') as data FROM files WHERE _id = ;
但是没有用。
有什么想法吗?
更新:问题可能与 SvelteKit 错误有关 - 请参阅 https://github.com/sveltejs/kit/issues/1438。
SvelteKit 中的限制已于 6 月 11 日解决。我还需要将 file.data 放入新的 Uint8Array...
// routes/api/file/[filenum].ts
import type { RequestHandler } from '@sveltejs/kit'
import { query } from '../_db'
export const get: RequestHandler = async ({ params }) => {
const { filenum } = params
const { rows } = await query(`SELECT * FROM find_file();`, [filenum])
if (rows) {
const file = rows[0]
return {
headers: {
'Content-Disposition': `attachment; filename="${file.name}"`,
'Content-Type': file.type
},
body: new Uint8Array(file.data)
}
} else return {
status: 404
}
}
这是 PostgreSQL 中 find_file() 函数的源代码:
CREATE OR REPLACE FUNCTION public.find_file(
integer,
OUT _id integer,
OUT name character varying,
OUT type character varying,
OUT data bytea)
RETURNS record
LANGUAGE 'sql'
COST 100
VOLATILE PARALLEL UNSAFE
AS $BODY$
SELECT _id, name, type, data FROM files WHERE _id = LIMIT 1
$BODY$;
和 query() 函数...
import pg from 'pg'
const pgNativePool = new pg.native.Pool({
max: 10, // default
connectionString: <string> import.meta.env.VITE_DATABASE_URL,
ssl: {
rejectUnauthorized: false
}
})
type QueryResponse = (sql: string, params?: Array<any>) => Promise<pg.QueryResult<any>>
export const query: QueryResponse = (sql: string, params?: Array<any>) => pgNativePool.query(sql, params)
将约 100 个 JPEG(每个 24K-100K)作为 bytea 列存储在 PostgreSQL 的 table 中。
<img/>
标签 src 属性引用 SvelteKit 端点:
<img src="/api/file/18.json" alt="Person"/>
出现此错误:
Invalid response from route /api/file/76.json: Uint8Array body must be accompanied by content-type: application/octet-stream header
export async function get({ params }) {
const { id } = params
const sql = `SELECT _id, name, type, data FROM files WHERE _id = ;`
const { rows } = await db.query(sql, [id])
const file = rows[0]
return {
headers: {
'Content-disposition': `attachment; filename=${file.name}`,
'Content-type': file.type
},
body: file.data
}
}
由于 SvelteKit endpoints 不与 req/res 对象交互,因为它们只在某些平台上可用,我不能只将 bytea 值作为流写到响应对象,但是我不确定正确的方法是什么。
也试过这个SQL语句...
SELECT _id, name, type, encode(data, 'base64') as data FROM files WHERE _id = ;
但是没有用。
有什么想法吗?
更新:问题可能与 SvelteKit 错误有关 - 请参阅 https://github.com/sveltejs/kit/issues/1438。
SvelteKit 中的限制已于 6 月 11 日解决。我还需要将 file.data 放入新的 Uint8Array...
// routes/api/file/[filenum].ts
import type { RequestHandler } from '@sveltejs/kit'
import { query } from '../_db'
export const get: RequestHandler = async ({ params }) => {
const { filenum } = params
const { rows } = await query(`SELECT * FROM find_file();`, [filenum])
if (rows) {
const file = rows[0]
return {
headers: {
'Content-Disposition': `attachment; filename="${file.name}"`,
'Content-Type': file.type
},
body: new Uint8Array(file.data)
}
} else return {
status: 404
}
}
这是 PostgreSQL 中 find_file() 函数的源代码:
CREATE OR REPLACE FUNCTION public.find_file(
integer,
OUT _id integer,
OUT name character varying,
OUT type character varying,
OUT data bytea)
RETURNS record
LANGUAGE 'sql'
COST 100
VOLATILE PARALLEL UNSAFE
AS $BODY$
SELECT _id, name, type, data FROM files WHERE _id = LIMIT 1
$BODY$;
和 query() 函数...
import pg from 'pg'
const pgNativePool = new pg.native.Pool({
max: 10, // default
connectionString: <string> import.meta.env.VITE_DATABASE_URL,
ssl: {
rejectUnauthorized: false
}
})
type QueryResponse = (sql: string, params?: Array<any>) => Promise<pg.QueryResult<any>>
export const query: QueryResponse = (sql: string, params?: Array<any>) => pgNativePool.query(sql, params)